<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./dist/vue.js"></script>
</head>
<body>
    <!-- 
      多个视图依赖于同一状态。来自不同视图的行为需要变更同一状态。
      
      一、vuex是什么？
         vuex是vue胚胎的公共数据管理工具，集中管理所有组件状态，方便组件之间共享数据。vuex中数据是响应式的，数据一发生变化，引用了数据的组件都会自动更新。vuex适合大型单页应用。页面刷新，vuex中的数据会丢失。
      二、简单介绍vuex:
         vuex实现了一个单向数据流，在全局拥有一个State来存放数据，当组件要更改State中的数据时，必须通过Mutation进行，Mutation同时提供了订阅者模式供外部插件获取和调用State数据的更新。而当所有异步操作(常见的异步操作：调用后端接口异步获取更新数据)或批量的同步操作需要走 action, 但action 也是无法直接修改state的，还是需要通过Mutation来修改State的数据，最后根据state的变化，渲染到视图上。
      三、vuex在项目中的使用 
        1. 创建仓储对象 ------ 在src 下创建一个文件夹 store
        2. 挂载： 在main.js 中 添加 store
          new Vue({
            router,
            store,
            render: h => h(App)
          }).$mount('#app')
        3. 介绍 store仓储对象的模块
          1) src > store > index.js: (导出 models 和 getters)
            export default new Vuex.Store({
              // 本来 store > index.js 中有state、mutation、getter、action等模块
              // 当数据比较庞大时，vuex可以将sore分割成模块module.每个模块拥有自己的 state、mutation、
              // getter、action
              modules: {
                user
              },
              getters
            })
          2) src > store > getters.js
            getters: 对store中的数据进行加工处理成新的数据，包装作用，不会修改store.类似于计算属性，state中数据改变，getter中也跟着改变。
            getters: {
              // 对store中的state进行加工处理
              showNum(state){
                return 500 + state.num
              }
               // 使用方式1：语句中：this.$store.getters.showNum ; 模板中 {{$store.getters.showNum}}
               // 使用方式2: 使用mapGetters 将getters数据映射到computed中。
               //  computed : { ...mapGetters(['showNum']) } --- 注意；此时模板中使用{{showNum}}
            }
          3) src > store > modules > user.js 
             namespaced: true, // 命名空间，调用actions和mutations时区分用的
             state: {
               num: 100
               // 状态管理容器对象，唯一公共数据源，专门用来存储数据，全局唯一，便于统一的状态管理。
               // 访问方式1：语句中：this.$store.state.num ; 模板中 {{$store.state.num}}
               // 访问方式2: 使用mapState 简化state在视图中的使用，将state数据映射到computed中。
               //  computed : { ...mapState(['num']) }
             }
             mutations: {
               // mutations 中存放修改state的同步方法，这样方便集中追踪数据变化。不推荐直接操作state数据。
               add(state, v) {
                 state.num += v
               }
               // 触发方式1：this.$store.commit('add', v)
               // 触发方式2：与mapState类似，使用mapMutations将mutations中的方法映射到methods中
               //  methods : { ...mapMutations['add'] }
             }
             actions: {
               // actions中存放修改state的异步方法，但还是得通过mutation间接变更数据
               async getUserList (context, data) {
                 const res = await getUserList({ num: data })
                 context.commit('change_num', res.data.data)
               }
               // 触发方式1: this.$store.dispatch(getUserList)
               // 触发方式2：与mapMutations类似，使用mapActions将actions中的方法映射到methods中。
               //  methods : { ...mapActions['getUserList'] }
             }
                /*  就需要在mutations 中再变更一下数据
                 mutations: {
                 change_num (state, data) {
                   state.num = data
                 }
               */
          
      四、介绍各模块在流程中的功能
        1) Vue components: vue组件，在Html页面上负责接收用户操作等交互行为，执行dispatch方法触发对应action进行回应
        2) dispatch:操作行为触发。是唯一能执行action的方法
        3) actions: 操作行为处理。由组件中的 $store.dispatch('action名称', data)来触发。然后由commit()来触发mutation的调用，间接更新state。负责处理 vue components 接收到的所有交互行为。
        4) commit: 状态改变提交。对mutation进行提交，是唯一能执行mutation的方法。
        5) mutations: 状态改变操作。由actions中的commit('mutation名称')来触发。是vuex修改state的唯一方法。该方法只能进行同步操作，且方法名只能全局唯一。
        6) state: 状态管理容器对象。集中存储vue.component这个data()对象的零散数据。全局唯一，便于统一的状态管理。
        7) getters: vue.components通过该方法读取全局state对象。
      五、为什么要用vuex?
        因为单向数据流中状态自管理应用包含以下几个部分：
        state:驱动应用的数据源
        view:以声明方式将state映射到视图
        actions:响应在view上的用户输入导致的状态变化
        但是，当我们的应用遇到多个组件共享状态时，单向数据流的简洁性很容易被破坏：因为
          多个视图依赖于同一状态 -- 如果是传参的方法来传递状态：多层嵌套和兄弟组件会很繁琐以及不受控制
          来自不同视图的行为需要变更同一状态 -- 如果采用父子组件直接引用或通过事件来变更和同步状态，会导致代码无法维护
        因此，我们要把组件的共同状态抽离出来，以一个全局单例模式管理
        这样：我们的组件树构成了一个巨大的"视图"，不管在树的哪个位置，任何组件都能获取状态或者触发行为
      六、什么情况下应该使用vuex?
        vuex可以帮助我们管理共享状态，并附带了更多的概念和框架，如果不打算开发大型单页应用，使用vuex可能是繁琐冗余的
        如果应用比较简单，最好不要使用 Vuex，一个简单的 store 模式 就足够了
        但是，如果需要构建一个中大型单页应用，就要使用vuex
      七、安装vuex
        npm install vuex --save / yarn add vuex
      八、vuex依赖Promise



      注意： 因为vuex能存储很多数据的状态，所以肯定需要配置。  src > strore  > index.js : import Vue from 'vue'   import Vuex from 'vuex'    Vue.use(Vuex)
      如果不像上面的 三、 分模块使用。 直接定义在 index.js中的配置是哪些?  --- 参考  ./ vue项目中的其他问题/index.js
      
     -->
    <div id="app">
    </div>
</body>
<script>
    new Vue({
        el:'#app',
        data () {
        }
    })
</script>
</html>